package middleware

import (
	"fmt"
	"io"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"good.house/internal/log"
)

type BodyWriter struct {
	gin.ResponseWriter
	body *strings.Builder
}

func (w *BodyWriter) Write(b []byte) (int, error) {
	w.body.Write(b)
	return w.ResponseWriter.Write(b)
}

func GinLogMiddleWare() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		requestStr := fmt.Sprintf("[GinRequest] %v	%s  %s  %s \n",
			time.Now().Format("2006/01/02 - 15:04:05"), ctx.Request.Method, ctx.Request.URL.Path, ctx.Request.RemoteAddr,
		)

		bw := &BodyWriter{
			ResponseWriter: ctx.Writer,
			body:           &strings.Builder{},
		}

		ctx.Writer = bw

		query := ctx.Request.URL.Query()

		queryStr := ""
		for key, value := range query {
			queryStr += fmt.Sprintf("%s=%s", key, strings.Join(value, ","))
		}

		queryStr = fmt.Sprintf("[Request Query] %s\n", queryStr)

		logger := log.GetLogger("fileAndConsole")

		logger.Info(requestStr)
		logger.Info(queryStr)

		if ctx.ContentType() == gin.MIMEJSON {
			body, _ := io.ReadAll(ctx.Request.Body)
			bodyStr := fmt.Sprintf("[Request Body] %s \n", body)
			logger.Info(bodyStr)

			ctx.Request.Body = io.NopCloser(strings.NewReader(string(body)))
		}

		ctx.Next()
		responseStr := fmt.Sprintf("[Response] path=%s	status=%d size=%d body=%s \n",
			ctx.Request.URL.Path, ctx.Writer.Status(), ctx.Writer.Size(), bw.body.String(),
		)

		logger.Info(responseStr)
	}
}
